<template>
  <div>
    <el-page-header @back="goBack" content="创建容器" class="back"></el-page-header>

    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="130px" class="demo-ruleForm" style="padding: 10px">
      <el-form-item label="容器名称" prop="name">
        <el-input v-model="ruleForm.name" placeholder="请输入容器名称"></el-input>
      </el-form-item>
    </el-form>

    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="130px" class="demo-ruleForm from">
      <div class="title">
        {{$t('AddContainer_imageSetting')}}
      </div>
      <el-form-item :label="$t('AddContainer_imageSource')" prop="imageUrl">
        <el-select v-model="ruleForm.imageUrl" :placeholder="$t('AddContainer_plsSelectImageSourcce')">
          <el-option label="DockerHub" value=""></el-option>
          <el-option :label="item.name" :value="item.url" v-for="item in hubdata" :key="item.name"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item :label="$t('AddContainer_containerImage')" prop="image">
        <SerchInput :serchdata="imageList" :image="ruleForm.image" @serchstate="serchstate"></SerchInput>
      </el-form-item>
      <el-form-item :label="$t('AddContainer_whetherAutoPullImage')" prop="isPullImage">
        <el-switch v-model="ruleForm.isPullImage"></el-switch>
      </el-form-item>
    </el-form>

    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="130px" class="demo-ruleForm from">
      <div class="title">
        {{$t('AddContainer_networkSetting')}}
      </div>
      <el-form-item :label="$t('AddContainer_syncHostOpenPort')" prop="isSynchronize">
        <el-switch v-model="ruleForm.isSynchronize"></el-switch>
      </el-form-item>
      <el-form-item :label="$t('AddContainer_manuallyPublishPort')" prop="isSynchronize">
        <el-button icon="iconfont icon-add" class="submit" size="mini" style="margin-left: 0" @click="addPort">添加</el-button>
      </el-form-item>
      <el-form-item :label="$t('AddContainer_plsInputHost')" prop="port" v-for="(item, index) in portNum" :key="item">
        <el-input :placeholder="$t('AddContainer_syncHostOpenPort')" v-model="ruleForm.port[index].host" style="width: 40%;">
          <template slot="prepend">{{$t('AddContainer_host')}}</template>
        </el-input>
        <el-input :placeholder="$t('AddContainer_plsInputContainerPort')" v-model="ruleForm.port[index].container" style="width: 40%;margin-left: 20px;">
          <template slot="prepend">{{$t('AddContainer_container')}}</template>
        </el-input>
        <el-button @click="delPort(item, index)" title="$t('AddContainer_delete')" type="danger" icon="iconfont icon-lajitong" style="margin-left: 10px; padding: 10px;" size="mini"></el-button>
      </el-form-item>
    </el-form>

    <el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="130px" class="demo-ruleForm from">
      <div class="title">
        {{$t('AddContainer_otherSettings')}}
      </div>
      <el-form-item :label="$t('AddContainer_autoDelete')" prop="autoRemove" title="$t('AddContainer_autoDeleteContainerAfterOnceUsed')">
        <el-switch v-model="ruleForm.autoRemove"></el-switch>
      </el-form-item>
    </el-form>
    <el-button @click="submitForm('ruleForm')" icon="iconfont icon-add" class="submit">{{$t('AddContainer_deployContainer')}}</el-button>
    <div class="tabbox">
      <AddTabs></AddTabs>
    </div>
  </div>
</template>

<script>
import Vue from 'vue'
import { Switch, RadioGroup, Radio, Form, FormItem, Select, Option, Input, Button, Popover, Table, TableColumn, Pagination, PageHeader } from 'element-ui'
import post from '@/utils/post'
import http from '@/utils/http'
import { Base64 } from 'js-base64' // 编码插件
import SerchInput from '@/components/SerchInput'
import AddTabs from '@/components/AddTabs'
Vue.use(Switch)
Vue.use(RadioGroup)
Vue.use(Radio)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Select)
Vue.use(Input)
Vue.use(Option)
Vue.use(Button)
Vue.use(Popover)
Vue.use(Table)
Vue.use(TableColumn)
Vue.use(Pagination)
Vue.use(PageHeader)

export default {
  data () {
    return {
      ruleForm: {
        name: '',
        imageUrl: '',
        image: '',
        isPullImage: false,
        port: [],
        isSynchronize: false,
        autoRemove: false
      },
      rules: {
        name: [
          { message: this.$t('AddContainer_plsInputContainerName'), trigger: 'blur' },
          { min: 3, max: 15, message: this.$t('AddContainer_lengthBetween3to15'), trigger: 'blur' }
        ],
        image: [
          { required: true, message: this.$t('AddContainer_plsInputContainer'), trigger: 'blur' }
        ]
      },
      hubdata: [],
      imageList: [],
      portNum: [],
      i: 0
    }
  },
  mounted () {
    // 进入创建页面，重置vuex中的创建容器数据。
    this.$store.commit('changeIsUpload', false)
    this.$store.commit('changeCrateData')

    // 请求全部的镜像数据列表
    const docker = 'curl --unix-socket /var/run/docker.sock -s "http:/v1.40/images/json?all=true"'
    post({ docker }, (res) => {
      this.imageList = res
      // console.log(res)
    }, this)
    // 请求hub注册表数据
    http({
      url: '/hubfind',
      method: 'GET',
      timeout: 2000000
    }).then(res => {
      this.hubdata = res.Data
    }).catch((err) => {
      return err
    })
  },
  methods: {
    // 处理镜像选择
    serchstate (state) {
      this.ruleForm.image = state
    },
    // 添加开放端口的input框
    addPort () {
      this.portNum.push(this.i)
      this.ruleForm.port.push({ host: '', container: '' })
      this.i++
    },
    // 删除开放端口的input框
    delPort (item, index) {
      this.portNum = this.portNum.filter(data => {
        return data !== item
      })
      this.ruleForm.port.splice(index, 1)
    },
    // 返回上一页
    goBack () {
      this.$router.go(-1)
    },
    // 提交事件
    submitForm (formName) {
      this.$refs[formName].validate((valid) => {
        if (valid) {
          // 创建容器
          this.$store.commit('changeIsUpload', true) // 改变vuex中isupload的状态，让子组件传参
          // 做一个延迟动画，等数据传回vuex后再添加，在vuex中监听changeCrateData是否调用9次。
          this.loading = this.$loading({
            lock: true,
            text: 'Loading',
            spinner: 'el-icon-loading',
            background: 'rgba(0, 0, 0, 0.7)'
          })
          setTimeout(() => {
            if (this.ruleForm.isPullImage) {
              this.pullImage()
            } else {
              this.createContainer()
            }
          }, 200)
        } else {
          return false
        }
      })
    },
    // 拉取镜像
    pullImage () {
      let name = this.ruleForm.image
      if (this.ruleForm.image.indexOf(':') === -1) {
        name = name + ':latest'
      }
      let docker = ''
      if (this.ruleForm.imageUrl) {
        const arr = this.hubdata.filter(item => {
          return item.url === this.ruleForm.imageUrl
        })
        const pulldata = {
          serveraddress: arr[0].url,
          username: arr[0].username,
          password: Base64.decode(arr[0].password)
        }
        const token = Base64.encode(JSON.stringify(pulldata))
        // console.log(token)
        docker = `curl -s -X POST --unix-socket /var/run/docker.sock --header "X-Registry-Auth: ${token}" http:/v1.40/images/create?fromImage=${name}`
      } else {
        docker = `curl --unix-socket /var/run/docker.sock -s -X POST "http:/v1.40/images/create?fromImage=${name}"` // 拉取镜像
      }
      post({ docker, timeout: 600000000 }, res => {
        this.loading.close()
        if (res.message) {
          return this.$message({
            showClose: true,
            message: res.message,
            type: 'error'
          })
        }
        if (res.status === 200) {
          this.$message({
            showClose: true,
            message: this.$t('AddContainer_containerPullSuccess'),
            type: 'success'
          })
          // 创建容器
          this.createContainer()
        } else {
          this.$message({
            showClose: true,
            message: this.$t('AddContainer_containerPullFailTryLater'),
            type: 'error'
          })
        }
      }, this)
    },
    // 提交创建容器
    createContainer () {
      const crateData = this.$store.state.crateData
      // 构建Volumes数据
      const Volumes = {}
      for (let a = 0; a < crateData.volumes.length; a++) {
        Volumes[crateData.volumes[a].container] = {}
      }
      // 构建NetworkingConfig数据
      const NetworkingConfig = {}
      NetworkingConfig.EndpointsConfig = {}
      NetworkingConfig.EndpointsConfig[crateData.netWorks.Network] = {
        IPAMConfig: {
          IPv4Address: crateData.netWorks.IPv4Address,
          IPv6Address: crateData.netWorks.IPv6Address
        }
      }
      // 构建Labels数据
      let Labels = {}
      for (let i = 0; i < crateData.Lables.length; i++) {
        Labels[crateData.Lables[i].key] = crateData.Lables[i].value
      }
      // 构建HostConfig数据
      let Binds = crateData.volumes.map(item => {
        return item.host + ':' + item.container
      })
      let CapAdd = []
      let CapDrop = []
      for (let key in crateData.Funs) {
        if (crateData.Funs[key]) {
          CapAdd.push(key)
        } else {
          CapDrop.push(key)
        }
      }
      let Devices = crateData.Rams.Devices.map(item => {
        return ({
          CgroupPermissions: 'rwm',
          PathInContainer: item.container,
          PathOnHost: item.host
        })
      })
      let Dns = []
      if (crateData.netWorks.PrimaryDNSServer || crateData.netWorks.SecondaryDNSServer) {
        Dns = [crateData.netWorks.PrimaryDNSServer, crateData.netWorks.SecondaryDNSServer]
      }
      let LogConfig = {}
      if (crateData.logs.drive) {
        let Config = {}
        for (let b = 0; b < crateData.logs.logsOption.length; b++) {
          Config[crateData.logs.logsOption[b].option] = crateData.logs.logsOption[b].value
        }
        LogConfig.Type = crateData.logs.drive
        LogConfig.Config = Config
      }

      let PortBindings = {}
      for (let c = 0; c < this.ruleForm.port.length; c++) {
        PortBindings[this.ruleForm.port[c].container + '/tcp'] = [{ HostPort: this.ruleForm.port[c].host }]
      }
      let HostConfig = {
        AutoRemove: this.ruleForm.autoRemove,
        Binds,
        CapAdd,
        CapDrop,
        Devices,
        Dns,
        ExtraHosts: [],
        LogConfig,
        Memory: crateData.Rams.Memorylimit * 1024 * 1024,
        MenoryReservation: crateData.Rams.Memoryreservation * 1024 * 1024,
        NanoCpus: crateData.Rams.CPUlimit * 100000000,
        NetworkMode: crateData.netWorks.Network,
        PortBindings,
        Privileged: crateData.Rams.Privileged,
        PublishAllPorts: this.ruleForm.isSynchronize,
        RestartPolicy: {
          Name: crateData.Restart
        },
        Runtime: crateData.Rams.Runtime
      }
      // 构建ExposedPorts数据
      let ExposedPorts = {}
      for (let j = 0; j < this.ruleForm.port.length; j++) {
        const key = this.ruleForm.port[j].container + '/tcp'
        ExposedPorts[key] = {}
      }
      // 构建Env数据
      let Env = crateData.Envs.map((item) => {
        return item.key + '=' + item.value
      })
      // 构建Cmd数据
      let Cmd = []
      if (crateData.command.commandName) {
        Cmd = crateData.command.commandName
      }
      // 构建整个大对象数据
      const data = {
        name: this.ruleForm.name,
        WorkingDir: crateData.command.workPath,
        Volumes,
        User: crateData.command.user,
        Tty: crateData.command.conlose === 'Tty' || crateData.command.conlose === 'Interactive&Tty',
        OpenStdin: crateData.command.conlose === 'Interactive' || crateData.command.conlose === 'Interactive&Tty',
        NetworkingConfig: NetworkingConfig,
        MacAddress: crateData.netWorks.MacAddress,
        Labels,
        Image: this.ruleForm.image,
        Hostname: crateData.netWorks.Hostname,
        HostConfig,
        ExposedPorts,
        Env,
        // Entrypoint: crateData.command.entryPoint // 入口点
        Domainname: crateData.netWorks.DomainName,
        Cmd
      }
      const docker = `curl --unix-socket /var/run/docker.sock -s -H Content-Type:application/json -d '${JSON.stringify(data)}' http:/v1.40/containers/create?name=${this.ruleForm.name}`
      post({ docker, timeout: 600000000 }, (res) => {
        this.loading.close()
        this.$store.commit('changeIsUpload', false) // 请求后恢复vuex的默认值
        if (res.message) {
          return this.$message({
            showClose: true,
            message: res.message,
            type: 'error'
          })
        }
        this.$message({
          showClose: true,
          message: this.$t('AddContainer_containerAddSuccess'),
          type: 'success'
        })
        // 启动容器
        this.startContiner(res.Id)
      }, this)
    },
    // 自动启动容器，不处理成功和失败
    startContiner (id) {
      const docker = `curl -w %{http_code} --unix-socket /var/run/docker.sock -s -X POST "http:/v1.40/containers/${id}/start"`
      post({ docker }, (res) => {
        this.$router.push('/Container')
      }, this)
    }
  },
  components: {
    SerchInput,
    AddTabs
  }
}
</script>

<style lang="scss" scoped>
.back{
  margin-bottom: 30px;
}
.title{
  font-size: 12px;
}
.from{
  border: 1px solid #067FB5;
  border-radius: 15px;
  padding: 20px 10px 0px 10px;
  margin: 30px 0px;
  background: #F7FCFF;
  position: relative;
  .title{
    position: absolute;
    top: -14px;
    z-index: 10;
    left: 30px;
    font-size: 18px;
    font-weight: bold;
    background: #F7FCFF;
    padding: 0px 5px;
    border-radius: 5px;
  }
}
.submit{
  background: #067FB5;
  color: #fff;
  margin-left: 30px;
}
.tabbox{
  margin-top: 30px;
  border-radius: 10px;
  border: 1px solid #067FB5;
  padding: 10px;
}
</style>
